package com.etong.frame.directive.impl.database;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.etong.frame.directive.DefaultDirective;
import com.etong.frame.directive.Directive;
import com.etong.frame.directive.Directive.OutputFormat;
import com.etong.frame.directive.GroupConfig;
import com.etong.frame.directive.checker.Checker;
import com.etong.frame.directive.checker.CheckerGroup;
import com.etong.frame.directive.factory.DirectiveExecutor;
import com.etong.frame.directive.mybatis.DirectiveStatementMapper;
import com.etong.frame.directive.util.CommonStatus;

public class DirectiveExecutorImpl implements DirectiveExecutor {
	protected static final Logger logger = LoggerFactory
			.getLogger(DirectiveExecutorImpl.class);
	private DirectiveStatementMapper directiveMapper;

	@Override
	public CommonStatus execute(Directive directive, Map<String, Object> vars) {
		DefaultDirective directiveImpl = (DefaultDirective) directive;

		// 生成可执行的sql语句
		CommonStatus status = null;
		status = directiveImpl.buildDirective(vars);
		if (!status.succeed()) {
			return status;
		}

		// 执行指令
		status = handleDirective(directiveImpl, status);
		if (!status.succeed()) {
			logger.error("Handle database directive error");
			return status;
		}

		// 调用检查器对执行结果进行检查
		CheckerGroup checkerGroup = directiveImpl.getCheckerGroup();
		if (null != checkerGroup) {
			for (Checker checker : checkerGroup.getCheckers()) {
				if (!checker.check(status.getObject())) {
					return checkError(checker, status);
				}
			}
		}

		return status;
	}

	protected CommonStatus checkError(Checker checker, CommonStatus status) {
		status.setStatus(null != checker.getCode() ? checker.getCode()
				: CommonStatus.DIRECTIVE_CHECK_ERROR);
		status.setMsg("Checker error:" + checker.getName());
		status.setToast(checker.getToast());
		return status;
	}

	/**
	 * @Title : handleDirective
	 * @Description : 执行数据库指令
	 * @params
	 * @param directive
	 * @param status
	 * @return 设定文件
	 * @return CommonStatus 返回类型
	 * @throws
	 */
	public CommonStatus handleDirective(DefaultDirective directive,
			CommonStatus status) {

		String sql = (String) status.getObject();

		Statement statement = (Statement) directive.getDirectiveConfig();
		Integer outputFormat = directive.getOutputFormat();
		Integer tableOp = statement.getTableOp();

		if (DatabaseDirective.BUILD_SELECT == tableOp
				|| DatabaseDirective.BUILD_COMMON == tableOp) {
			status = handleSelect(statement, sql, outputFormat);
		} else if (DatabaseDirective.BUILD_DELETE == tableOp) {
			status = handleDelete(statement, sql);
		} else if (DatabaseDirective.BUILD_INSERT == tableOp) {
			status = handleInsert(statement, sql);
		} else if (DatabaseDirective.BUILD_REPLACE == tableOp) {
			status = handleReplace(statement, sql);
		} else if (DatabaseDirective.BUILD_UPDATE == tableOp) {
			status = handleUpdate(statement, sql);
		} else if (DatabaseDirective.BUILD_COUNT == tableOp) {
			status = handleCount(statement, sql);
		}
		return status;
	}

	public CommonStatus handleInsert(Statement statement, String sql) {
		CommonStatus status = new CommonStatus();
		status.setObject(directiveMapper.execInsert(sql));
		return status;
	}

	public CommonStatus handleReplace(Statement statement, String sql) {
		CommonStatus status = new CommonStatus();
		status.setObject(directiveMapper.execInsert(sql));
		return status;
	}

	public CommonStatus handleUpdate(Statement statement, String sql) {
		CommonStatus status = new CommonStatus();
		status.setObject(directiveMapper.execUpdate(sql));
		return status;
	}

	public CommonStatus handleDelete(Statement statement, String sql) {
		CommonStatus status = new CommonStatus();
		status.setObject(directiveMapper.execDelete(sql));
		return status;
	}

	public CommonStatus handleSelect(Statement statement, String sql,
			Integer outputFormat) {

		CommonStatus status = new CommonStatus();
		if (OutputFormat.ONE.equals(outputFormat)) {
			status.setObject(directiveMapper.execSelectOne(sql));
		} else if (OutputFormat.LIST.equals(outputFormat)) {
			status.setObject(directiveMapper.execSelectList(sql));
		} else if (OutputFormat.INT.equals(outputFormat)) {
			status.setObject(directiveMapper.execSelectInt(sql));
		} else {
			status.setObject(directiveMapper.execSelectList(sql));
		}
		return status;
	}

	public CommonStatus handleCount(Statement statement, String sql) {
		CommonStatus status = new CommonStatus();
		status.setObject(directiveMapper.execSelectInt(sql));
		return status;
	}

	@Override
	public CommonStatus execute(Directive directive, Map<String, Object> vars,
			GroupConfig groupConfig) {
		DefaultDirective directiveImpl = (DefaultDirective) directive;

		// 生成可执行的sql语句
		CommonStatus status = null;
		status = directiveImpl.buildDirective(vars);
		if (!status.succeed()) {
			return status;
		}

		// 执行指令
		status = handleDirective(directiveImpl, status);
		if (!status.succeed()) {
			logger.error("Handle database directive error");
			return status;
		}

		// 调用检查器对执行结果进行检查
		CheckerGroup checkerGroup = groupConfig.getCheckerGroup();
		if (null != checkerGroup) {
			for (Checker checker : checkerGroup.getCheckers()) {
				if (!checker.check(status.getObject())) {
					return checkError(checker, status);
				}
			}
		}

		return status;
	}

	public DirectiveStatementMapper getDirectiveMapper() {
		return directiveMapper;
	}

	public void setDirectiveMapper(DirectiveStatementMapper directiveMapper) {
		this.directiveMapper = directiveMapper;
	}
}
